#include "../include/gui/UiEditor.hpp"
#include "../include/gui/ScrollArea.hpp"
#include "../include/gui/GridLayout.hpp"
#include "../include/gui/GuiManager.hpp"


namespace gui
{
	UiEditor::UiEditor(GuiManager* gui)
	{
		m_type = UI_EDITOR;
		m_gui = gui;
		m_gridLayout = NULL;
		m_scrollArea = NULL;
		m_allowSave = false;
		CreateInterface();
		m_gui->SetEditMode(true);	//you're now in edit-mode	
	}

	UiEditor::~UiEditor()
	{
		m_gui->SetEditMode(false);
	}

	void UiEditor::CreateInterface()
	{
		uint32 height = (uint32)m_gui->GetWindow().GetView().GetHalfSize().y*2;
		
		//this->SetPos(25,25,true);
		this->Resize(150,height-100);

		m_gridLayout = new GridLayout;
		m_gridLayout->SetVerticalPolicy(Widget::MaximumExpand);
		m_gridLayout->SetHorizontalPolicy(Widget::MinimumExpand);
		m_gridLayout->SetName("GRID_LAYOUT");
		m_gridLayout->Resize(m_rect.w,m_rect.h);
		m_gridLayout->SetMovable(false);
		m_gridLayout->m_editMode = false;

		//need to resize the scroll area when the gridLayout resizes to fit the widgets
		m_mediator.Connect(m_gridLayout,"default",gui::events::OnResize,false);

		ScrollArea* sa = new ScrollArea;
		m_scrollArea = sa;
		sa->SetName("scroll_area");
		sa->Resize(m_rect.w,m_rect.h);
		sa->SetScrollArea(Rect(0,0,m_rect.w,m_rect.h));
		sa->FindChildByName("grid_layout")->m_editMode = false;
		sa->m_editMode = false;
		sa->SetMovable(false);

		sa->AddWidget(m_gridLayout);
		AddWidget(sa);
		sf::Vector2f pos = sa->GetView()->GetPos();
		m_gridLayout->SetPos((int)pos.x,(int)pos.y,true);

		//add all possible *registered in factories* widgets to the grid layout
		for(uint32 i=0; i< m_gui->m_factories.size(); i++) {
			AbstractFactory* factory = m_gui->m_factories[i];

			const Rangeu& range = factory->GetWidgetRange();
			uint32 count = 0;
			for(uint32 j=range.GetLowerLimit(); j!=range.GetUpperLimit(); j++) {
				Widget* widget = factory->CreateWidget(j);
				if(!widget) {
					error_log("Factory said it can create widget of type %u, yet it returned NULL!", j);
					continue;
				}
				//for debug only!

				std::string name = typeid(*widget).name();
				widget->SetName(name);
				m_gridLayout->AddWidgetToGrid(widget,count,0);

				//notify me when use drags a widget
				m_mediator.Connect(widget,"default",gui::events::OnDragCreated,false);
				m_mediator.Connect(widget,"default",gui::events::OnDragStarted,false);
				count++;
			}
		}
	}

	void UiEditor::Update(float diff)
	{
		Widget::Update(diff);

		Drag* drag = m_gui->m_curDrag;
		if(drag) {
			Widget* widget = drag->GetTarget();
			GridLayout* view = (GridLayout*)m_scrollArea->GetView()->FindChildByName("GRID_LAYOUT");
			if(!view) {
				error_log("Couldn't find view's grid layout!");
				return;
			}
			std::vector<Widget*> prop = m_gui->GetWidgetsByType(UI_PROPERTIES);
			if(prop.size()) {
				for(uint32 i=0; i<prop.size(); i++) {
					if(prop[i]->ContainsWidget(widget))
					{
						return;
					}
				}
			}
			
			if(!ContainsWidget(widget)) {
				widget->m_editMode = true;
				drag->SetForcedMove(true);
			}
		}

		gui::Event* e;
		while(e = m_mediator.GetEvent())
		{
			switch(e->GetType())
			{
			case gui::events::OnDragCreated:
			{
				gui::OnDragCreated* d = (gui::OnDragCreated*)e;
				Drag* drag =  d->GetDrag();
				drag->SetMinDragDist(40);
				drag->SetForcedMove(true);

			} break;
			case gui::events::OnDragStarted:
			{
				gui::OnDragMoved* d = (gui::OnDragMoved*)e;
				Drag* drag =  d->GetDrag();

				float hotspotWidthPct  = drag->GetHotSpot().x/d->GetWidget()->GetSize().x;
				float hotspotHeightPct = drag->GetHotSpot().y/d->GetWidget()->GetSize().y;

				//create a similar widget, and add it to the gui
				Widget* widget = m_gui->CreateWidget(drag->GetTarget()->GetType());
				if(!widget) {
					error_log("Tried to create a similar widget, but failed! This should never happen!");
					continue;
				}
				widget->Resize(widget->GetSizeHint().x, widget->GetSizeHint().y);
				std::string name = typeid(*widget).name();
				widget->SetName(name);
				s_gui->AddWidgetForced(widget);
				sf::Vector2f hotspotPos;
				hotspotPos.x = widget->GetSize().x * hotspotWidthPct;
				hotspotPos.y = widget->GetSize().y * hotspotHeightPct;

				drag = new Drag(widget,NULL);
				drag->SetHotSpot(hotspotPos);
				drag->SetForcedMove(true);
				drag->SetDragFlags(Drag::Anywhere);
				drag->m_status = Drag::Running;	//start the drag instantly

				//register the new drag(will reset the position of the current target)
				m_gui->RegisterDrag(drag);


			} break;
			case gui::events::OnResize:
			{
				gui::OnResize* r = (gui::OnResize*)e;
				Widget* target = r->GetWidget();
				if(target != m_gridLayout)
					continue;
				Rect rect = target->GetRect();
				m_scrollArea->SetScrollArea(rect);
			} break;
			default: 
				error_log("Received unexpected event type: %u", e->GetType());
			}
		}
	}

}